#include <iostream>
using namespace std;


// polymorhpism can happen only when the type are cast compatible
struct T {
    virtual T operator+(const T& t2)=0;
	virtual void print() const =0;
};

struct T1 : public T {
    float val;
    T1 (float v=0.0) : val(v) {}
    T1 operator+(const T& t2){
        const T1& other = (const T1&) t2;
        T1 res;
        cout << "T1 +" << endl;
        res.val = (val + other.val);
        return res;
    }

	void print() const {
		cout << val << endl;
	}
};

struct T2 : public T {
    int val;
    T2 (int v=0) : val(v) {}
   	T2 operator+(const T& t2){
        const T2& other = (const T2&) t2;
        T2 res;
        cout << "T2 +" << endl;
        res.val = (val + other.val);
        return res;
    }

	void print() const{
		cout << val << endl;
	}
 
};

int main()
{
    T1 a(1.1);
    T1 b(2.2);
    T2 c(3);
    T2 d(4);

	(a+b).print();
	(c+d).print();


    return 0;
}
